package com.power.sifa.approve.controller;

import cn.hutool.core.util.ObjectUtil;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.file.model.MockMultipartFile;
import com.plf.common.utils.PdfConvertUtil;
import com.plf.core.base.model.Ha_attachment;
import com.power.external.window.api.IWindowFeign;
import com.power.sifa.approve.api.IBusinessApprove;
import com.power.sifa.approve.model.Apl_limit_hear;
import com.power.sifa.approve.model.Aprv_materials_options;
import com.power.sifa.approve.model.doc.AbstractDoc;
import com.power.sifa.approve.model.doc.HearAuditDelayDoc;
import com.power.sifa.approve.model.enumeration.Tp_procmaterialEnum;
import com.power.sifa.approve.service.Apl_limit_hearService;
import com.power.sifa.approve.service.Apl_mainService;
import com.power.sifa.approve.service.Aprv_materials_optionsService;
import com.power.sifa.approve.service.BusinessApproveService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
public class BusinessApproveController implements IBusinessApprove {

    @Resource
    private BusinessApproveService businessApproveService;
    @Resource
    private Apl_limit_hearService apl_limit_hearService;
    @Resource
    private Aprv_materials_optionsService aprv_materials_optionsService;
    @Resource
    private Apl_mainService apl_mainService;

    @Override
    public ResponseDTO startBusinessProced(String applyid, String proctype, String userid, String username, String processinstanceid, String cause, String describe, Map<String, Object> docfield) {
        try {
            Map<String, String> result = this.businessApproveService.startBusinessProced(applyid, proctype, userid, username, processinstanceid, cause, describe, docfield);
            return ResponseDTO.succData(result);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("/businessapprove/startBusinessProced 启动一个业务子流程失败 ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, e.getMessage());
        }

    }

    @Override
    public ResponseDTO weekdayDeadline(String applyid, Integer days) {
        // 通过applyid 查询限制时间
        Apl_limit_hear apl_limit_hear = apl_limit_hearService.getById(applyid);
        if (ObjectUtil.isNotNull(apl_limit_hear)) {
            Date endDate = apl_limit_hear.getEnddate();
            Date dealLineDate = this.businessApproveService.getTargetDay(endDate, days);
            SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
            Map<String, String> dateMap = new HashMap<>();
            dateMap.put("endDate", fmt.format(endDate));
            dateMap.put("dealLineDate", fmt.format(dealLineDate));
            return ResponseDTO.succData(dateMap);
        }
        return ResponseDTO.wrap(500, "当前配置的截止时间为空");
    }

    /**
     * 在线预览doc文件
     *
     * @param request
     * @param response
     * @param applyid
     * @param proctype
     * @param docfield
     * @return
     */
    @Override
    public ResponseDTO previewDecisionDoc(HttpServletRequest request, HttpServletResponse response, String applyid, String proctype, Map<String, Object> docfield) {
        try (InputStream stream = this.businessApproveService.previewDecisionDoc(applyid, proctype, docfield);
             OutputStream outputStream = response.getOutputStream()) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Content-Disposition", "attachment; filename=" + "file.docx");
            IOUtils.write(IOUtils.toByteArray(stream), outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "previewDecisionDoc 在线预览失败");
        }
        return ResponseDTO.succ();
    }

    @Override
    public ResponseDTO previewApproveDoc(String applyid, String modelKey, Map<String, Object> formData) throws Exception {
        try {
            Ha_attachment attachment = this.businessApproveService.previewApproveDoc(applyid, modelKey, formData);
            return ResponseDTO.succData(attachment);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "previewApproveDoc 在线预览失败");
        }
    }

    /**
     * FIXME: 之前用于表单编辑预览，后被在线编辑替代(弃用)
     * 通过文件名匹配文件生成文件流返回预览
     *
     * @param request
     * @param response
     * @param applyid
     * @param materilaType
     * @param docfield
     * @return
     * @throws Exception
     */
    @Override
    public ResponseDTO previewDocByDocName(HttpServletRequest request, HttpServletResponse response, String applyid, Integer materilaType, Map<String, Object> docfield) throws Exception {
        Assert.notNull(materilaType, "文件类型不能为空");
        Assert.notNull(applyid, "业务申请id不能为空");
        try (InputStream stream = this.businessApproveService.previewDocByDocName(applyid, materilaType, docfield);
             OutputStream outputStream = response.getOutputStream()) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Content-Disposition", "attachment; filename=" + "file.docx");
            IOUtils.write(IOUtils.toByteArray(stream), outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "previewApproveDoc 在线预览失败");
        }
        return ResponseDTO.succ();
    }

    /**
     * FIXME: 之前用于表单编辑预览，后被在线编辑替代(弃用)
     * 初始化获取对应的文件参数
     *
     * @param applyid
     * @param materilaType
     * @return
     * @throws Exception
     */
    @Override
    public ResponseDTO savePreviewDocPdfByDocName(HttpServletRequest request, HttpServletResponse response, String applyid, Integer materilaType, Map<String, Object> docfield) throws Exception {
        Assert.notNull(materilaType, "文件类型不能为空");
        Assert.notNull(applyid, "业务申请id不能为空");
        try (InputStream stream = this.businessApproveService.previewDocByDocName(applyid, materilaType, docfield);
             OutputStream outputStream = response.getOutputStream()) {
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Content-Disposition", "attachment; filename=" + "file.docx");
            // 转换为pdf
            byte[] pdfByte = PdfConvertUtil.word2pdfWithFont(stream);
            IOUtils.write(IOUtils.toByteArray(new ByteArrayInputStream(pdfByte)), outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "previewApproveDoc 在线预览失败");
        }
        return ResponseDTO.succ();
    }

    /**
     * FIXME: 之前用于表单编辑预览，后被在线编辑替代(弃用)
     * 获取对应的前端参数
     *
     * @param applyid
     * @param materilaType
     * @return
     * @throws Exception
     */
    @Override
    public ResponseDTO initPreviewDocParam(String applyid, Integer materilaType) throws Exception {
        Assert.notNull(materilaType, "文件类型不能为空");
        Assert.notNull(applyid, "业务申请id不能为空");
        AbstractDoc doc = this.businessApproveService.initBeforeProcess(applyid, materilaType);
        return ResponseDTO.succData(doc);
    }


    /**
     * 输入流转换为对应的文件
     *
     * @param inputStream
     * @param originalFilename
     * @param contentType
     * @return
     * @throws IOException
     */
    public MultipartFile convert(InputStream inputStream, String originalFilename, String contentType) throws IOException {
        return new MockMultipartFile(originalFilename, originalFilename, contentType, inputStream);
    }

    /**
     * FIXME: 之前用于表单编辑预览，后被在线编辑替代(弃用)
     * 预览文件进行保存
     *
     * @param applyid
     * @param materilaType
     * @param busiType
     * @param userName
     * @param docfield
     * @return
     * @throws Exception
     */
    @Override
    public ResponseDTO savePreviewDocByMaterial(String applyid, Integer materilaType, Integer busiType, String userId, String userName, Map<String, Object> docfield) throws Exception {
        Assert.notNull(applyid, "业务申请id不能为空");
        Assert.notNull(materilaType, "材料类型不能为空");
        Assert.notNull(busiType, "业务申请id不能为空");
        // 生成对应的文件返回
        // 判断当前的材料类型
        Tp_procmaterialEnum procmaterialEnum = Tp_procmaterialEnum.getById(materilaType);
        if (ObjectUtil.isNull(procmaterialEnum)) {
            return ResponseDTO.wrap(500, "未查询到对应文件类型");
        }
        try {
            // 1. 预览文件保存为pdf返回
            Ha_attachment attachment = this.businessApproveService.previewDocSaveToPdf(applyid, materilaType, docfield);
            // 2. 保存操作记录的文件
            Aprv_materials_options optionsData = this.aprv_materials_optionsService.saveOptionMaterial(attachment,
                    applyid, busiType, userId, userName, procmaterialEnum, docfield);

            // 延期审理通知书
            if (Tp_procmaterialEnum.HEAR_DELAY.getId().equals(materilaType)) {
                HearAuditDelayDoc auditDelayDoc = new HearAuditDelayDoc();
                auditDelayDoc.transDate(docfield);
                return ResponseDTO.succData(docfield);
            }
            return ResponseDTO.succData(optionsData);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "保存文件失败");
        }
    }

    /**
     * FIXME: 之前用于表单编辑预览，后被在线编辑替代(弃用)
     * 对应的表单绑定材料更新
     *
     * @param optionid
     * @param userId
     * @param userName
     * @param docfield
     * @return
     * @throws Exception
     */
    @Override
    public ResponseDTO updatePreviewDocByMaterial(String optionid, String userId, String userName, Map<String, Object> docfield) throws Exception {
        Assert.notNull(optionid, "表单记录id不能为空");
        // 生成对应的文件返回
        // 获取之前版本的记录
        Aprv_materials_options options = this.aprv_materials_optionsService.getById(optionid);
        if (ObjectUtil.isNull(options)) {
            return ResponseDTO.wrap(500, "当前未查询到对应材料的记录");
        }
        try {
            Ha_attachment attachment = this.businessApproveService.previewDocSaveToPdf(options.getApplyid(), options.getMattype(), docfield);
            return ResponseDTO.succData(this.aprv_materials_optionsService.updateOptionMaterial(attachment,
                    options.getApplyid(), optionid, options.getProctype(), userId, userName, docfield));
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return ResponseDTO.wrap(500, "保存文件失败");
        }
    }


    /**
     * 盖章材料测试 (临时)
     *
     * @return
     */
    @Override
    public ResponseDTO templateStamp(String applyid, Integer proctype) {
        businessApproveService.templateStamp(applyid, proctype);
        return ResponseDTO.succ();
    }

    /**
     * 盖章材料格式转换 (临时)
     *
     * @return
     */
    @Override
    public ResponseDTO transSignMaterial() {
        businessApproveService.transSignMaterial();
        return ResponseDTO.succ();
    }
    @Resource
    private IWindowFeign iWindowFeign;
    public ResponseDTO triggerExecute() {
//        List<String> list = new ArrayList<>(10);
//        list.add("17115034157305lP8zi7xLb9hFdo6EDeQm");
//        list.add("1711075007615FzqYQUDwbgPI0VLhDFOlk");
//        list.add("1711088413358Cek8nnVeWLSxvXoCjE1TL");
//        list.add("1711088408087znGFbtJbcv_uSp8IggyKZ");
//        list.add("1711503611998p8ZfrbFlTec62WMpGVFHF");

//        for (String id : list) {
//            Apl_main mainObj = this.apl_mainService.getById(id);
//            // 受理结果通知
//            ApproveVo appVo = new ApproveVo();
//            appVo.setOpinion("准许受理");
//            appVo.setResult("1"); // 1 受理 0 不予受理
//            appVo.setUserid(mainObj.getAcceptuserid());
//            appVo.setUsername(mainObj.getAcceptusername());
//            appVo.setTime(mainObj.getAccepttime());
//            ResponseDTO conRef = this.iWindowFeign.confirmAccept(mainObj.getId(), appVo);
//            if(0 != conRef.getCode()) {
//                log.error("向一窗推送受理结果失败 applyid -> {}", mainObj.getId());
//            }
//            // 办结结果通知
//            FinishVo finVo = new FinishVo();
//            finVo.setOpinion("许可通过");
//            finVo.setResult("1"); // 0 不予许可, 1 许可通过, 109 审批出件, 96 退件办结
//            finVo.setUserid(mainObj.getAcceptuserid());
//            finVo.setUsername(mainObj.getAcceptusername());
//            finVo.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
//            finVo.setLicenceName("行政复议受理通知书");
//            finVo.setLicenceCode(mainObj.getAcceptcode());
//            ResponseDTO subRes = this.iWindowFeign.submitResult(mainObj.getId(), finVo);
//            if(0 != subRes.getCode()) {
//                log.error("向一窗推送业务办理结果失败 applyid -> {}", mainObj.getId());
//            }
//        }

//        AdmreAuditAccept acceptObj = new AdmreAuditAccept();
//        Map<String, Object> initdata = new HashMap<>(16);
//        initdata.put("userid", "c17afc971d934f2b952b296c3d477dcb");
//        initdata.put("username", "龚欢");
//        initdata.put("sectionid", "3601001000");
//        initdata.put("sectionname", "南昌市司法局");
//        initdata.put("deptid", "3601001002");
//        initdata.put("deptname", "行政复议受理科");
//        initdata.put("adid", "360100");
//        initdata.put("taskname", "校验");
//        initdata.put("applyid", "17113384593820FPovCz2hwIc4zMyHehUt");
////      acceptObj.init(initdata);
//        AdmreAuditAcceptCheck acceptcheckObj = new AdmreAuditAcceptCheck();
//        acceptObj.init(initdata);
//        acceptcheckObj.init(initdata);
        try {
//            acceptObj.execute();
//            acceptcheckObj.init(initdata);


            return ResponseDTO.succ();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("AdmreAuditAcceptCheck 执行失败 ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "执行失败");
        }
    }

    @Override
    public ResponseDTO changeDecisionType(String f_applyid, String applyid, Integer decisiontype, Integer decisiontypeid, String decisiontypename) {
        try {
            this.businessApproveService.changeDecisionType(f_applyid, applyid, decisiontype,decisiontypeid,decisiontypename);
            return ResponseDTO.succ();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("更新流程中的决定状态失败 ->  msg[{}]", e.getMessage());
            return ResponseDTO.wrap(500, "更新流程中的决定状态失败");
        }
    }


}
